package com.rc.common.util;

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.boot.json.JsonParseException;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.concurrent.Callable;


public class JsonUtil {
    private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    static {
        OBJECT_MAPPER.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        OBJECT_MAPPER.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        OBJECT_MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        OBJECT_MAPPER.registerModule(new JavaTimeModule());
        OBJECT_MAPPER.registerModule(simpleModule);
    }


    public static ObjectMapper getMapper(){
        return OBJECT_MAPPER;
    }

    public static <T>T tryParse(Callable<T> parse){
        return tryParse(parse, JacksonException.class);
    }

    public static String toJson(Object object){
        return tryParse(() -> OBJECT_MAPPER.writeValueAsString(object));
    }

    public static <T> T toObj(String json, Class<T> elementClass){
        return tryParse(() -> OBJECT_MAPPER.readValue(json, elementClass));
    }

    public static <T> List<T> toObjList(String json,Class<T> elementClass){
        //泛型会丢失
        CollectionType listType = OBJECT_MAPPER.getTypeFactory().constructCollectionType(List.class, elementClass);
        return tryParse(() -> OBJECT_MAPPER.readValue(json, listType));
    }

    public static <T> T toObj(String json,TypeReference<T> type){
        return tryParse(() -> OBJECT_MAPPER.readValue(json, type));
    }


    public static <T>T tryParse(Callable<T> parser,Class<? extends Exception> check){
        try {
            return parser.call();
        } catch (Exception e) {
            if (check.isAssignableFrom(e.getClass())){
                throw new JsonParseException(e);
            }
            throw new IllegalStateException(e);
        }
    }
}
